﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once

#include "GcmpDevService.h"
#include <atomic>

namespace gcmp
{
    /// \brief 可以被WeakPtr<T>引用的对象的基类
    /// \see WeakPtr
    class GCMP_DEV_SERVICE_EXPORT WeakReferenceable
    {
    public:
        /// \brief 构造函数
        WeakReferenceable();

        /// \brief 析构函数
        virtual ~WeakReferenceable(void);

        /// \brief 拷贝构造函数
        WeakReferenceable(const WeakReferenceable& other);

        /// \brief 拷贝赋值
        WeakReferenceable& operator=(const WeakReferenceable& other);

    private:
        template<class T> friend class WeakPtr;
        class GCMP_DEV_SERVICE_EXPORT Proxy
        {
            CANNOT_COPY_OR_ASSIGN(Proxy);
        public:
            explicit Proxy(WeakReferenceable* pObject) : m_pObject(pObject), m_refCount(0) {}
            ~Proxy() { if (m_pObject) m_pObject->m_pProxy = nullptr;}
            WeakReferenceable* operator->() { return m_pObject; }
            const WeakReferenceable* operator->() const { return m_pObject; }
            WeakReferenceable& operator*() { return *m_pObject; }
            const WeakReferenceable& operator*() const { return *m_pObject; }
            WeakReferenceable* Get() { return m_pObject; }
            const WeakReferenceable* Get() const { return m_pObject; }
            void Reset() {m_pObject = nullptr;}
            void Ref() {m_refCount++;}
            void UnRef() {if (--m_refCount==0) delete this;}
            bool IsValid() {return m_pObject != nullptr;}
        private:
            friend class WeakReferenceable;
            // 指向被代理的对象
            WeakReferenceable* m_pObject;
            // 有多少weakptr引用到m_pObject
            std::atomic<int> m_refCount;
        };

        Proxy* GetOrCreateProxy() const;
private:
        mutable Proxy* m_pProxy;
    };
}


